home *** CD-ROM | disk | FTP | other *** search
Wrap
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <ctype.h> #include <errno.h> #include <aes.h> #include <tos.h> #include <ext.h> #include <time.h> #include "cookie.h" #include "inetcust.h" #include "tcpdef.h" #include "ftp.h" #define SYSBASE ((SYSHDR*)0x4f2L) static BASPAG **oldpd; long set_pd(void); long restore_pd(void); #define noDEBUG #define noRCVDEBUG #define noSNDDEBUG #define noDIRDEBUG #define DOLOG #define noDOLOGRCV #define DISKFREE #define ASCII_TYPE 0 #define IMAGE_TYPE 1 #define DOLOGICAL_TYPE 2 #define FILEBUFSIZE 8192 #define FTP_CMD 21 #define FTP_DATA 20 #define USER_CMD 1 #define ACCT_CMD 2 #define PASS_CMD 3 #define TYPE_CMD 4 #define LIST_CMD 5 #define CWD_CMD 6 #define DELE_CMD 7 #define CDUP_CMD 8 #define QUIT_CMD 9 #define RETR_CMD 10 #define STOR_CMD 11 #define PORT_CMD 12 #define NLST_CMD 13 #define PWD_CMD 14 #define XPWD_CMD 15 #define MKD_CMD 16 #define XMKD_CMD 17 #define XRMD_CMD 18 #define RMD_CMD 19 #define STRU_CMD 20 #define MODE_CMD 21 #define HELP_CMD 22 #define STAT_CMD 23 static char *commands[] = { "xx", "user", "acct", "pass", "type", "list", "cwd", "dele", "cdup", "quit", "retr", "stor", "port", "nlst", "pwd", "xpwd", "mkd", "xmkd", "xrmd", "rmd", "stru", "mode", "help", "stat", " ", NULL }; static char types[] = "AIL"; /* Response messages */ static char banner[] = "220-TUW experimental FTP-Server (version %s) for ATARI ready\r\n220 (c)pm, hw fortec 1992,93\r\n"; static char badcmd[] = "500 Unknown command\r\n"; static char givepass[] = "331 Enter PASS command\r\n"; static char logged[] = "230-Login OK\r\n230 \"%s\" is current directory\r\n"; static char typeok[] = "200 Type %s OK\r\n"; static char only8[] = "501 Only logical bytesize 8 supported\r\n"; static char deleok[] = "250 File deleted\r\n"; static char mkdok[] = "200 MKD ok\r\n"; static char delefail[] = "550 Delete failed: %s\r\n"; static char pwdmsg[] = "257 \"%s\" is current directory\r\n"; static char badtype[] = "501 Unknown type \"%s\"\r\n"; static char badport[] = "501 Bad port syntax\r\n"; static char unimp[] = "502 Command not yet implemented\r\n"; static char bye[] = "221 Goodbye!\r\n"; static char nodir[] = "553 Cannot change to \"%s\"\r\n"; static char cantopen[] = "550 Can't read file \"%s\": %s\r\n"; static char sending[] = "150 Opening data connection for %s %s\r\n"; static char cantmake[] = "553 Can't create \"%s\": %s\r\n"; static char writerr[] = "552 Write error: %s\r\n"; static char portok[] = "200 Port command okay\r\n"; static char rxok[] = "226 File received OK\r\n"; static char txok[] = "226 File sent OK\r\n"; static char noperm[] = "550 Permission denied\r\n"; static char logincor[] = "550 Login incorrect\r\n"; static char noconn[] = "425 Data connection reset\r\n"; static char notlog[] = "530 Please log in with USER and PASS\r\n"; static char userfirst[] ="503 Login with USER first.\r\n"; static char helptxt1[] ="214-The following commands are recognized:\r\n"; static char helptxt2[] ="214 End of command list.\r\n"; static char stattxt1[] ="211-TUW-FTP server status:\r\n"; static char stattxt2[] ="211 End of TUW-FTP server status.\r\n"; extern int log(char *); extern FTP ftp; static char filebuf[FILEBUFSIZE]; static char str[200]; static char logstr[200]; static char reply[200]; static int type = IMAGE_TYPE; static int logbsize; static DESTI fport; static char keeppath[128], userpath[128], ftppath[128]="C:\\"; static char trusted = 0; static int ftp_data; static char nullbyte = 0; static time_t timer; int check_passwd(char *,char *); int write_log(char *); int pport(DESTI *,char *); void dosify(char *); int cwd(char *); void undosify(char *); int dodir(FTP *,int,char *); int dosend(FTP *,char *); int dorecv(FTP *,char *); extern int handle_message( int pipe[8] ); int test_trust(char *dirpath, int mode); void getpath(char *path); static void serv_event_loop( void ) { int x, y, kstate, key, clicks, event, state; int pipe[8]; event = evnt_multi( MU_MESAG | MU_TIMER, 2, 0x1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pipe, 10, 0, &x, &y, &state, &kstate, &key, &clicks ); if( event & MU_MESAG) { wind_update(BEG_UPDATE); handle_message( pipe ); wind_update(END_UPDATE); } } int ftpserv(FTP *ftp) { TCPSTAT ftpstat; int i; char *cmd; char *arg; long state; if(ftp->cmd == QUIT) { if(ftp->ftp_ctl > 0) tcp_close(ftp->ftp_ctl); return(-2); } if(ftp->ftp_ctl <= 0) { ftp->ftp_ctl = (int)tcp_open(FTP_CMD,NULL,PASSIV,0,256L); if(ftp->ftp_ctl <= 0) { log("cannot listen on ftp-port"); return(-1); } ftp->cmd = STARTUP; return(0); } if(ftp->cmd == STARTUP) { state = tcp_stat(ftp->ftp_ctl,&ftpstat); if(state == ESTABLISHED) { i = sprintf(str,banner,FTP_VERSION); tcp_write(ftp->ftp_ctl,str,i,PUSH,NO_URGENT); ftp->fport = ftpstat.TCP_Dest; #ifdef DOLOG time(&timer); sprintf(logstr,"connection opened from %u.%u.%u.%u at %s",ftpstat.TCP_Dest.IPAddr[0],ftpstat.TCP_Dest.IPAddr[1],ftpstat.TCP_Dest.IPAddr[2],ftpstat.TCP_Dest.IPAddr[3],ctime(&timer)); log(logstr); write_log(logstr); #endif ftp->cmd = IDLE; return(1); } else return(0); } if(ftp->cmd == RETR_CMD) { return(dosend(ftp,NULL)); } if(ftp->cmd == STOR_CMD) { #ifdef DOLOG log("reenter dorecv"); #endif return(dorecv(ftp,NULL)); } ftp->cmd = IDLE; i = (int)tcp_read(ftp->ftp_ctl,str,(int)sizeof(str)-1); /* sprintf(logstr,"%d-%d\n",ftp->ftp_ctl,i); log(logstr);*/ if(i < 0) { #ifdef DOLOG state = tcp_stat(ftp->ftp_ctl,&ftpstat); time(&timer); sprintf(logstr,"connection broken from %u.%u.%u.%u at %s",ftpstat.TCP_Dest.IPAddr[0],ftpstat.TCP_Dest.IPAddr[1],ftpstat.TCP_Dest.IPAddr[2],ftpstat.TCP_Dest.IPAddr[3],ctime(&timer)); log(logstr); write_log(logstr); #endif tcp_close(ftp->ftp_ctl); return(2); } if(i == 0) return(0); str[i] = '\0'; cmd = strtok(str," \t\r\n"); arg = strtok(NULL,"\r\n"); if(arg == NULL) arg = &nullbyte; #ifdef DEBUG if(!arg) printf("<%s>\n",cmd); else printf("<%s> <%s>\n",cmd,arg); #endif strlwr(cmd); for(i = 1; commands[i]; i++) { if(!strcmp(commands[i],cmd)) break; } if(!ftp->logged_in && i != USER_CMD && i != PASS_CMD && i != QUIT_CMD) { tcp_write(ftp->ftp_ctl,notlog,(int)strlen(notlog),PUSH,NO_URGENT); return(0); } switch(i) { case USER_CMD: strcpy(ftp->username,arg); ftp->logged_in = 0; tcp_write(ftp->ftp_ctl,givepass,(int)strlen(givepass),PUSH,NO_URGENT); break; case ACCT_CMD: tcp_write(ftp->ftp_ctl,unimp,(int)strlen(unimp),PUSH,NO_URGENT); break; case PASS_CMD: if(!ftp->username[0]) { tcp_write(ftp->ftp_ctl,userfirst,(int)strlen(userfirst),PUSH,NO_URGENT); break; } if(!check_passwd(ftp->username,arg)) { time(&timer); sprintf(str,"login user '%s' from %u.%u.%u.%u failed at %s",ftp->username,ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3],ctime(&timer)); write_log(str); log(logstr); tcp_write(ftp->ftp_ctl,logincor,(int)strlen(logincor),PUSH,NO_URGENT); } else { ftp->logged_in = 1; #ifdef DOLOG time(&timer); sprintf(str,"user '%s' logged in from %u.%u.%u.%u at %s",ftp->username,ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3],ctime(&timer)); write_log(str); log(str); #endif Supexec(set_pd); sprintf(str,logged,ftppath); Supexec(restore_pd); undosify(str); tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); } break; case TYPE_CMD: switch(arg[0]) { case 'A': case 'a': /* Ascii */ type = ASCII_TYPE; sprintf(reply,typeok,arg); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); break; case 'l': case 'L': if(!arg || *arg == '\0' || *++arg != '8') { tcp_write(ftp->ftp_ctl,only8,(int)strlen(only8),PUSH,NO_URGENT); break; } type = DOLOGICAL_TYPE; logbsize = 8; sprintf(reply,typeok,arg); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); break; case 'B': case 'b': /* Binary */ case 'I': case 'i': /* Image */ type = IMAGE_TYPE; sprintf(reply,typeok,arg); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); break; default: /* Invalid */ sprintf(reply,badtype,arg); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); break; } break; case LIST_CMD: dodir(ftp,1,arg); break; case CDUP_CMD: arg = ".."; /* fall thru */ case CWD_CMD: #ifdef DOLOG sprintf(logstr,"CHDIR to '%s'",arg); log(logstr); #endif dosify(arg); if(test_trust(arg,0)) { Supexec(set_pd); if(arg[1] == ':') { Dsetdrv(toupper(arg[0]) - 'A'); } if(Dsetpath(arg)) { #ifdef DOLOG log("CHDIR failed"); #endif /* Failed, don't change anything */ undosify(arg); sprintf(reply,nodir,arg); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); Supexec(restore_pd); break; } getpath(keeppath); Supexec(restore_pd); } else tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT); /* fall through */ case PWD_CMD: case XPWD_CMD: Supexec(set_pd); sprintf(str,pwdmsg,ftppath); undosify(str); tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); Supexec(restore_pd); break; case HELP_CMD: { int i; tcp_write(ftp->ftp_ctl,helptxt1,(int)strlen(helptxt1),PUSH,NO_URGENT); i=1; while(commands[i]) { sprintf(str," %6s%6s%6s%6s%6s%6s%6s%6s\r\n", commands[i],commands[i+1],commands[i+2],commands[i+3], commands[i+4],commands[i+5],commands[i+6],commands[i+7]); i += 8; tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); } tcp_write(ftp->ftp_ctl,helptxt2,(int)strlen(helptxt2),PUSH,NO_URGENT); } break; case STAT_CMD: tcp_write(ftp->ftp_ctl,stattxt1,(int)strlen(stattxt1),PUSH,NO_URGENT); sprintf(str," TUW-FTP Version %s\r\n",FTP_VERSION); tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); sprintf(str," Connected to %u.%u.%u.%u\r\n",ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3]); tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); sprintf(str," Logged in as %s\r\n",ftp->username); tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); sprintf(str," Type: %c, FORM: N; STRUcture: F; transfer MODE: S\r\n",types[type]); tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); sprintf(str," No data connection\r\n"); tcp_write(ftp->ftp_ctl,str,(int)strlen(str),PUSH,NO_URGENT); tcp_write(ftp->ftp_ctl,stattxt2,(int)strlen(stattxt2),PUSH,NO_URGENT); break; case DELE_CMD: Supexec(set_pd); errno = 0; dosify(arg); if(trusted) { if(arg && !unlink(arg)) { #ifdef DOLOG sprintf(reply,"DELE file '%s'",arg); log(reply); #endif tcp_write(ftp->ftp_ctl,deleok,(int)strlen(deleok),PUSH,NO_URGENT); } else { sprintf(reply,delefail,sys_errlist[errno]); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); } } else { tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT); } Supexec(restore_pd); break; case QUIT_CMD: ftp->logged_in = 0; #ifdef DOLOG time(&timer); sprintf(logstr,"logout user '%s' from %u.%u.%u.%u at %s",ftp->username,ftp->fport.IPAddr[0],ftp->fport.IPAddr[1],ftp->fport.IPAddr[2],ftp->fport.IPAddr[3],ctime(&timer)); log(logstr); write_log(logstr); #endif ftp->username[0] = 0; tcp_write(ftp->ftp_ctl,bye,(int)strlen(bye),PUSH,NO_URGENT); #ifdef DOLOG log("closing connection..."); #endif tcp_close(ftp->ftp_ctl); #ifdef DOLOG log("cmd connection closed"); #endif return(2); case RETR_CMD: dosend(ftp,arg); break; case STOR_CMD: dorecv(ftp,arg); break; case PORT_CMD: if(pport(&ftp->fport,arg) == -1) { tcp_write(ftp->ftp_ctl,badport,(int)strlen(badport),PUSH,NO_URGENT); } else { tcp_write(ftp->ftp_ctl,portok,(int)strlen(portok),PUSH,NO_URGENT); } break; case NLST_CMD: dodir(ftp,0,arg); break; case MKD_CMD: case XMKD_CMD: Supexec(set_pd); dosify(arg); if(trusted) { if(Dcreate(arg) >= 0) { Supexec(restore_pd); #ifdef DOLOG undosify(arg); sprintf(reply,"MKDIR '%s' successful",arg); log(reply); write_log(reply); #endif tcp_write(ftp->ftp_ctl,mkdok,(int)strlen(mkdok),PUSH,NO_URGENT); } else { Supexec(restore_pd); #ifdef DOLOG undosify(arg); sprintf(reply,"MKDIR '%s' failed",arg); log(reply); write_log(reply); #endif sprintf(reply,cantmake,arg,""); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); } } else tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT); break; case XRMD_CMD: case RMD_CMD: Supexec(set_pd); dosify(arg); if(trusted) { if(!Ddelete(arg)) { Supexec(restore_pd); #ifdef DOLOG sprintf(reply,"RMDIR '%s' successful",arg); log(reply); write_log(reply); #endif tcp_write(ftp->ftp_ctl,deleok,(int)strlen(deleok),PUSH,NO_URGENT); } else { Supexec(restore_pd); #ifdef DOLOG sprintf(reply,"RMDIR '%s' failed",arg); log(reply); write_log(reply); #endif sprintf(reply,delefail,sys_errlist[ENOENT]); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); } } else tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT); break; case STRU_CMD: case MODE_CMD: default: tcp_write(ftp->ftp_ctl,badcmd,(int)strlen(badcmd),PUSH,NO_URGENT); break; } return(0); } int check_passwd(char *user,char *passwd) { int found; char all_user[10], all_pass[10]; char nulchar = 0; extern INETCUST *custom; extern FILE *fp_pass; if(user == NULL) return 0; if(passwd == NULL) passwd = &nulchar; Supexec(set_pd); if((fp_pass = fopen(custom->passwd,"r")) == NULL) { Supexec(restore_pd); return 0; } found = 0; while(!feof(fp_pass)) { fscanf(fp_pass,"%8[^:]%*[^:]:%8[^:]%*[^:]:%128[^\n]%*[^\n]\n",all_user,all_pass,userpath); if( !strncmp(all_user,user,8) && (!strncmp(all_pass,passwd,8) || !strncmp(all_pass,"",8))) { found = 1; if(userpath[0] == '*') { trusted = 1; strcpy(ftppath,"C:\\"); } else { strupr(userpath); strcpy(ftppath,userpath); trusted = 0; } Dsetdrv(toupper(ftppath[0])-'A'); Dsetpath(&ftppath[2]); break; } } fclose(fp_pass); Supexec(restore_pd); return found; } int write_log(char *text) { extern INETCUST *custom; extern FILE *fp_pass; int found; Supexec(set_pd); if((fp_pass = fopen("C:\\ETC\\XFERLOG","a")) == NULL) { Supexec(restore_pd); return 0; } found = (fputs(text,fp_pass) != EOF); fputs("\n",fp_pass); fclose(fp_pass); Supexec(restore_pd); return(found); } int pport(DESTI *fport,char *arg) { long n; int i; n = 0; for(i=0;i<4;i++) { n = atoi(arg) + (n << 8); if((arg = strchr(arg,',')) == NULL) return -1; arg++; } *(long *)fport->IPAddr = n; n = atoi(arg); if((arg = strchr(arg,',')) == NULL) return -1; arg++; n = atol(arg) + (n << 8); fport->Port = (unsigned int)n; return 0; } void undosify(char *s) { while(*s != '\0'){ if(*s == '\\') *s = '/'; s++; } } void dosify(char *s) { strupr(s); while(*s != '\0'){ if(*s == '/') *s = '\\'; s++; } } int dodir(FTP *ftp,int list,char *dirpath) { long state; long fsum = 0; int nfiles = 0; TCPSTAT tstat; struct ffblk de; /* directory entry */ DISKINFO di; int found; int sent,x; if(list == 0 && *dirpath == '-') { list = 1; dirpath = strrchr(dirpath,' '); if(*dirpath) dirpath++; } dosify(dirpath); if(!(*dirpath) || dirpath[strlen(dirpath)-1] == '\\' || dirpath[strlen(dirpath)-1] == ':') strcat(dirpath,"*.*"); if(!test_trust(dirpath,1)) { tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT); Supexec(restore_pd); return 0; } Supexec(set_pd); sprintf(reply,sending,"dir",dirpath); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); if((strlen(dirpath) == 2) && dirpath[1] == ':') strcat(dirpath,"\\*.*"); #ifdef DOLOG sprintf(reply,"sending directory %s",dirpath); log(reply); #endif ftp_data = (int)tcp_open(FTP_DATA,&ftp->fport,AKTIV,20,1024L); while((state = tcp_stat(ftp_data,&tstat)) < ESTABLISHED && ftp_data > 0) { serv_event_loop(); } if(state == ESTABLISHED) { #ifdef DIRDEBUG printf("data connection opened for DIR '%s'\n",dirpath); #endif if(!findfirst(dirpath,&de,FA_DIREC | FA_SYSTEM | FA_HIDDEN | FA_ARCH)) { found = 1; if(!strrchr(dirpath,'*') && (de.ff_attrib & FA_DIREC) && de.ff_name[0] != '.') { #ifdef DIRDEBUG printf("list directory",dirpath); #endif strcat(dirpath,"\\*.*"); found = !findfirst(dirpath,&de,FA_DIREC | FA_SYSTEM | FA_HIDDEN | FA_ARCH); } while(found) { if(de.ff_name[0] != '.') { if(list) { if(de.ff_attrib & FA_DIREC) { sprintf(str,"%-12s <DIR> ",de.ff_name); } else { sprintf(str,"%-12s%7ld ",strlwr(de.ff_name),de.ff_fsize); fsum += de.ff_fsize; } sprintf(str+strlen(str)," %2.2d:%2.2d %2.2d.%2.2d.%4.4d\r\n", (de.ff_ftime >> 11) & 0x1f, /* hour */ (de.ff_ftime >> 5) & 0x3f, /* minute */ (de.ff_fdate ) & 0x1f, /* day */ (de.ff_fdate >> 5) & 0xf, /* month */ (de.ff_fdate >> 9) + 1980); /* year */ } else { strcpy(str,strlwr(de.ff_name)); strcat(str,"\r\n"); } #ifdef DIRDEBUG printf(str); #endif sent = 0; nfiles++; while(sent < strlen(str)) { if((x=(int)tcp_write(ftp_data,str+sent,(int)strlen(str)-sent,NO_PUSH,NO_URGENT)) < 0) { tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT); tcp_close(ftp_data); ftp_data = -1; break; } else if(x) { sent += x; } else { tcp_stat(ftp_data,&tstat); if(tstat.TCP_State != ESTABLISHED) { tcp_close(ftp_data); ftp_data = -1; break; } } serv_event_loop(); } if(ftp_data < 0) break; } found = !findnext(&de); } if(ftp_data < 0) { #ifdef DOLOG log("data connection closed"); #endif tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT); #ifdef DOLOG log("sending directory broken"); #endif Supexec(restore_pd); return(0); } #ifdef DISKFREE Dfree(&di,0); sprintf(reply,"%5u files %10lu bytes\r\n" " %10lu bytes free\r\n", nfiles,fsum,di.b_free*di.b_secsiz*di.b_clsiz); #else sprintf(reply,"\r\n"); #endif if(list) tcp_write(ftp_data,reply,(int)strlen(reply),PUSH,NO_URGENT); tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT); tcp_close(ftp_data); ftp_data = -1; #ifdef DOLOG log("data connection closed"); #endif #ifdef DOLOG log("sending directory ok"); #endif } else { #ifdef DOLOG log("directory empty"); #endif tcp_close(ftp_data); ftp_data = -1; tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT); } } else { #ifdef DOLOG log("cannot create data connection"); #endif tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT); ftp_data = -1; } Supexec(restore_pd); return(0); } int dosend(FTP *ftp,char *dirpath) { long state; TCPSTAT tstat; int length; int x; int sent; int file; #ifdef DOLOG long t; #endif long s; dosify(dirpath); if(!test_trust(dirpath,1)) { tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT); return 0; } sprintf(reply,sending,"RETR",dirpath); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); sprintf(reply,"sending '%s'",dirpath); write_log(reply); #ifdef DOLOG log(reply); #endif Supexec(set_pd); file = (int)Fopen(dirpath,FO_READ); Supexec(restore_pd); undosify(dirpath); if(file < 0) { #ifdef DOLOG sprintf(reply,"cannot open '%s': %s",dirpath,sys_errlist[ENOENT]); log(reply); #endif sprintf(reply,cantopen,dirpath,sys_errlist[ENOENT]); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,URGENT); return(0); } ftp_data = (int)tcp_open(FTP_DATA,&ftp->fport,AKTIV,20,(long)FILEBUFSIZE); while((state = tcp_stat(ftp_data,&tstat)) < ESTABLISHED && ftp_data > 0 ) { serv_event_loop(); } if(state == ESTABLISHED) { #ifdef DOLOG /* printf("data connection opened for RETR '%s'\n",dirpath); */ t = clock(); #endif s = 0; Supexec(set_pd); while((length = (int)Fread(file,FILEBUFSIZE,filebuf)) > 0) { Supexec(restore_pd); sent = 0; serv_event_loop(); while(length) { x = (int)tcp_write(ftp_data,filebuf+sent,length,PUSH,NO_URGENT); if(x < 0) { tcp_close(ftp_data); ftp_data = -1; break; } else if(x) { sent += x; length -= x; s += x; } else { tcp_stat(ftp_data,&tstat); if(tstat.TCP_State != ESTABLISHED) { tcp_close(ftp_data); ftp_data = -1; break; } } serv_event_loop(); } if(ftp_data < 0) break; Supexec(set_pd); } Supexec(restore_pd); } else { tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT); return(0); } #ifdef DOLOG t = (clock() -t) * 5; sprintf(reply,"%ld bytes in %ld msec , %ld kBytes/sec" ,s,t, s / t); log(reply); #endif if(ftp_data < 0) { #ifdef DOLOG sprintf(reply,"error %d sending '%s': %s",errno,dirpath,sys_errlist[errno]); log(reply); #endif sprintf(reply,cantopen,dirpath,sys_errlist[ESPIPE]); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,URGENT); } else { tcp_write(ftp->ftp_ctl,txok,(int)strlen(txok),PUSH,NO_URGENT); #ifdef DOLOG log("send file ok"); #endif } if(ftp_data > 0) tcp_close(ftp_data); ftp_data = -1; Supexec(set_pd); Fclose(file); Supexec(restore_pd); return(0); } int dorecv(FTP *ftp,char *dirpath) { long state; TCPSTAT tstat; long filelen = 0; long length; int done; int file; #ifdef DOLOGRCV long cnt; cnt = 0; #endif if(!trusted) { tcp_write(ftp->ftp_ctl,noperm,(int)strlen(noperm),PUSH,NO_URGENT); return 0; } done = 0; sprintf(reply,sending,"STOR",dirpath); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); dosify(dirpath); #ifdef DOLOG sprintf(reply,"receiving '%s'",dirpath); log(reply); write_log(reply); #endif ftp_data = (int)tcp_open(FTP_DATA,&ftp->fport,AKTIV,20,(long)FILEBUFSIZE); while((state = tcp_stat(ftp_data,&tstat)) < ESTABLISHED && ftp_data > 0) { serv_event_loop(); } if(state == ESTABLISHED) { #ifdef RCVDEBUG printf("data connection opened for STOR '%s'\n",dirpath); #endif #ifdef DOLOG sprintf(reply,"opened for STOR '%s'",dirpath); log(reply); #endif Supexec(set_pd); file = (int)Fcreate(dirpath,0); Supexec(restore_pd); undosify(dirpath); if(file < 0) { sprintf(reply,cantmake,dirpath,sys_errlist[ENODEV]); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,NO_URGENT); #ifdef DOLOG sprintf(reply,"cannot create '%s':%s",dirpath,sys_errlist[ENODEV]); log(reply); #endif done = -2; } else do { serv_event_loop(); length = tcp_read(ftp_data,filebuf,(unsigned int)FILEBUFSIZE); if(length == 0) { state = tcp_stat(ftp_data,&tstat); #ifdef DOLOGRCV cnt++; #endif if(state == ESTABLISHED) continue; else done = 1; } else if(length < 0) done = 1; else { Supexec(set_pd); if(((Fwrite(file,length,filebuf)) != length)) { done = -1; #ifdef DOLOGRCV sprintf(reply,"write error %ld",err); log(reply); #endif #ifdef RCVDEBUG printf("recv or write error\n"); #endif } else { filelen += length; } Supexec(restore_pd); } #ifdef DOLOGRCV sprintf(reply,"%ld x 0, now %ld, stored %ld bytes",cnt,length,filelen); log(reply); cnt = 0; #endif } while(!done); } else { tcp_write(ftp->ftp_ctl,noconn,(int)strlen(noconn),PUSH,NO_URGENT); return(0); } #ifdef RCVDEBUG printf("data connection closed\n"); #endif #ifdef DOLOG sprintf(reply,"data connection closed"); log(reply); #endif if(done == -1) { #ifdef DOLOG log("error writing file"); #endif sprintf(reply,writerr,sys_errlist[ENOSPC]); tcp_write(ftp->ftp_ctl,reply,(int)strlen(reply),PUSH,URGENT); tcp_abort(ftp_data); } else if(done > 0) { tcp_write(ftp->ftp_ctl,rxok,(int)strlen(rxok),PUSH,NO_URGENT); #ifdef DOLOG log("receive ok"); #endif } tcp_close(ftp_data); ftp_data = -1; Supexec(set_pd); if(file >= 0) Fclose(file); Supexec(restore_pd); return(0); } void getpath(char *path) { path[0] = (char)(Dgetdrv()+'A'); path[1] = ':'; Dgetpath(&path[2],0); if(path[1] == ':' && path[2] == 0) strcat(path,"\\"); } long set_pd(void) { oldpd = SYSBASE->_run; SYSBASE->_run = &_BasPag; getpath(keeppath); Dsetdrv(toupper(ftppath[0])-'A'); Dsetpath(&ftppath[2]); return 0; } long restore_pd(void) { SYSBASE->_run = oldpd; getpath(ftppath); Dsetdrv(toupper(keeppath[0])-'A'); Dsetpath(&keeppath[2]); return 0; } int test_trust(char *dirpath, int mode) { char oldpath[128]; char *ppath; if(trusted) return 1; Supexec(set_pd); if(dirpath[1] == ':') Dsetdrv(toupper(dirpath[0])-'A'); strcpy(oldpath,dirpath); if(mode == 1) { if((ppath = strrchr(oldpath,'\\')) == NULL) strcpy(oldpath,"."); else *ppath = 0; if(oldpath[2] == 0 && oldpath[1] == ':') strcat(oldpath,"\\"); } Dsetpath(oldpath); getpath(oldpath); Dsetdrv(toupper(ftppath[0])-'A'); Dsetpath(&ftppath[2]); Supexec(restore_pd); if(!strncmp(oldpath,userpath,strlen(userpath))) return 1; else return 0; } void closetcp(void) { tcp_close(ftp.ftp_ctl); tcp_close(ftp_data); }